package org.jeecg.modules.gis.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.geotools.geojson.geom.GeometryJSON;
import org.geotools.geometry.jts.JTS;
import org.geotools.referencing.CRS;
import org.locationtech.jts.geom.*;
import org.locationtech.jts.linearref.LengthLocationMap;
import org.locationtech.jts.linearref.LinearLocation;
import org.locationtech.jts.linearref.LocationIndexedLine;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;

/**
 * description: 网格工具 [描述信息]
 *
 * @author zhoumingyang [作者]
 * @version 1.0.0 [版本信息]
 * @date 2022/05/27 15:48:16 [时间，这里是年/月/日 时:分:秒的格式]
 */
@Component
public class GeometryTypeUtil {
    @Autowired
    private  GeometryFactory geometryFactory;

    public JSONObject polygonToGeoJson(Polygon polygon) throws IOException {
        GeometryJSON geometryJSON = new GeometryJSON(7);
        StringWriter sw = new StringWriter();
        geometryJSON.writePolygon(polygon, sw);
        JSONObject pgJson = JSONObject.parseObject(sw.toString());
        return pgJson;
    }

    public JSONObject lineStringToGeoJson(LineString lineString) throws IOException {
        GeometryJSON geometryJSON = new GeometryJSON(7);
        StringWriter sw = new StringWriter();
        geometryJSON.writeLine(lineString, sw);
        JSONObject lnJson = JSONObject.parseObject(sw.toString());
        return lnJson;
    }

    public JSONObject pointToGeoJson(Point point) throws IOException {
        GeometryJSON geometryJSON = new GeometryJSON(7);
        StringWriter sw = new StringWriter();
        geometryJSON.writePoint(point, sw);
        JSONObject ptJson = JSONObject.parseObject(sw.toString());
        return ptJson;
    }

    public JSONObject lineJsonToFeatureJson(JSONObject lnJson) throws IOException {
        JSONObject featureJson = new JSONObject();
        JSONObject properties = new JSONObject();
        featureJson.put("type", "Feature");
        featureJson.put("properties", properties);
        JSONObject geometryJson = new JSONObject();
        geometryJson.put("type", "LineString");
        geometryJson.put("coordinates", lnJson.get("coordinates"));
        featureJson.put("geometry", geometryJson);
        return featureJson;
    }

    public JSONObject pointJsonToFeatureJson(JSONObject ptJson, JSONObject properties) throws IOException {
        JSONObject featureJson = new JSONObject();
        featureJson.put("type", "Feature");
        featureJson.put("properties", properties);
        JSONObject geometryJson = new JSONObject();
        geometryJson.put("type", "Point");
        geometryJson.put("coordinates", ptJson.get("coordinates"));
        featureJson.put("geometry", geometryJson);
        return featureJson;
    }

    public JSONObject featureJsonToFeatureCollectionJson(JSONArray features) throws IOException {
        JSONObject featureCollectionJson = new JSONObject();
        if (features.isEmpty()) {
            return featureCollectionJson;
        }
        featureCollectionJson.put("type", "FeatureCollection");
        featureCollectionJson.put("features", features);
        return featureCollectionJson;
    }

    //替换xy位置
    public LineString replaceXY(LineString lineString) throws IOException {
        GeometryJSON geometryJSON = new GeometryJSON(7);
        JSONObject lnJson = lineStringToGeoJson(lineString);
        JSONArray lns = lnJson.getJSONArray("coordinates");
        for (int i = 0; i < lns.size(); i++) {
            JSONArray pt = lns.getJSONArray(i);
            double x = pt.getDouble(0);
            double y = pt.getDouble(1);
            pt.set(0, y);
            pt.set(1, x);
        }
        Geometry mgeo = geometryJSON.read(new StringReader(JSON.toJSONString(lnJson)));
        return (LineString) mgeo;
    }

    //替换xy位置
    public Point replaceXY(Point point) throws IOException {
        GeometryJSON geometryJSON = new GeometryJSON(7);
        StringWriter sw = new StringWriter();
        geometryJSON.writePoint(point, sw);
        JSONObject ptJson = JSONObject.parseObject(sw.toString());
        JSONArray pts = ptJson.getJSONArray("coordinates");
        double x = pts.getDouble(0);
        double y = pts.getDouble(1);
        pts.set(0, y);
        pts.set(1, x);

        Geometry mgeo = geometryJSON.read(new StringReader(JSON.toJSONString(ptJson)));
        return (Point) mgeo;
    }

    //4326转3857
    public Geometry c4326to3857(Geometry geo) throws IOException, FactoryException, TransformException {
        CoordinateReferenceSystem wd84 = CRS.decode("EPSG:4326");
        CoordinateReferenceSystem prj84 = CRS.decode("EPSG:3857");
        MathTransform wdToPrj = CRS.findMathTransform(wd84, prj84);
        Geometry geoPrj = (LineString) JTS.transform(geo, wdToPrj);
        return geoPrj;
    }

    //3857转4326
    public Geometry c3857to4326(Geometry geo) throws IOException, FactoryException, TransformException {
        CoordinateReferenceSystem wd84 = CRS.decode("EPSG:4326");
        CoordinateReferenceSystem prj84 = CRS.decode("EPSG:3857");
        MathTransform prjTOWd = CRS.findMathTransform(prj84, wd84);
        Geometry geoWd = JTS.transform(geo, prjTOWd);
        return geoWd;
    }

    public Point lengthOnLineString2(Geometry roadLine, double length) {
        LocationIndexedLine locationIndexedLine = new LocationIndexedLine(roadLine);
        LinearLocation linearLocation = LengthLocationMap.getLocation(roadLine, length);
        Coordinate result = locationIndexedLine.extractPoint(linearLocation);
        Point point = geometryFactory.createPoint(result);
        return point;
    }
}
